package com.hh.service.impl;

import cn.hutool.core.util.ObjUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hh.common.ErrorCode;
import com.hh.entity.domain.Blog;
import com.hh.entity.domain.User;
import com.hh.entity.dto.analyze.BlogAnalyzeRequest;
import com.hh.entity.dto.analyze.BlogCategoryAnalyzeRequest;
import com.hh.entity.dto.analyze.BlogUserAnalyzeRequest;
import com.hh.entity.vo.analyze.BlogCategoryAnalyzeResponse;
import com.hh.entity.vo.analyze.BlogTagAnalyzeResponse;
import com.hh.entity.vo.analyze.BlogUserAnalyzeResponse;
import com.hh.exception.BusinessException;
import com.hh.exception.ThrowUtils;
import com.hh.service.BlogAnalyzeService;
import com.hh.service.BlogService;
import com.hh.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author hanhui
 * @version 1.0
 * @description: TODO
 * @date 2025/10/5 14:07
 **/
@Service
@Slf4j
public class BlogAnalyzeServiceImpl implements BlogAnalyzeService {

    @Resource
    private UserService userService;
    @Resource
    private BlogService blogService;


    /**
     * 获取博客用户分析数据
     *
     * @param blogUserAnalyzeRequest 博客用户分析请求参数
     * @param loginUser              当前登录用户
     * @return 博客用户分析响应列表
     */
    @Override
    public List<BlogUserAnalyzeResponse> getBlogUserAnalyze(BlogUserAnalyzeRequest blogUserAnalyzeRequest, User loginUser) {
        // 参数校验：如果请求参数为空，则抛出参数错误异常
        ThrowUtils.throwIf(blogUserAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
        // 检查权限
        checkSpaceAnalyzeAuth(blogUserAnalyzeRequest, loginUser);

        // 构造查询条件
        QueryWrapper<Blog> queryWrapper = new QueryWrapper<>();
        fillAnalyzeQueryWrapper(blogUserAnalyzeRequest, queryWrapper);

        // 分析维度：每日、每周、每月
        String timeDimension = blogUserAnalyzeRequest.getTimeDimension();
        switch (timeDimension) {
            case "day":
                queryWrapper.select("DATE_FORMAT(createTime, '%Y-%m-%d') AS period", "COUNT(*) AS count");
                break;
            case "week":
                queryWrapper.select("YEARWEEK(createTime) AS period", "COUNT(*) AS count");
                break;
            case "month":
                queryWrapper.select("DATE_FORMAT(createTime, '%Y-%m') AS period", "COUNT(*) AS count");
                break;
            default:
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "不支持的时间维度");
        }

        // 分组和排序
        queryWrapper.groupBy("period").orderByAsc("period");

        // 查询结果并转换
        List<Map<String, Object>> queryResult = blogService.getBaseMapper().selectMaps(queryWrapper);
        return queryResult.stream()
                .map(result -> {
                    String period = result.get("period").toString();
                    Long count = ((Number) result.get("count")).longValue();
                    return new BlogUserAnalyzeResponse(period, count);
                })
                .collect(Collectors.toList());
    }


    /**
     * 获取博客标签分析结果
     *
     * @param blogAnalyzeRequest 博客分析请求参数
     * @param loginUser          登录用户信息
     * @return 返回标签分析结果列表，包含标签名称和出现次数
     */
    @Override
    public List<BlogTagAnalyzeResponse> getBlogTagAnalyze(BlogAnalyzeRequest blogAnalyzeRequest, User loginUser) {
        // 检查请求参数是否为空，为空则抛出参数错误异常
        ThrowUtils.throwIf(blogAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
        // 检查用户是否有权限进行空间分析
        if (loginUser != null) {
            checkSpaceAnalyzeAuth(blogAnalyzeRequest, loginUser);
        }
        // 创建查询条件包装器
        QueryWrapper<Blog> queryWrapper = new QueryWrapper<>();
        // 填充查询条件
        fillAnalyzeQueryWrapper(blogAnalyzeRequest, queryWrapper);
        // 只查询tags字段
        queryWrapper.select("tags");
        // 从数据库中查询tags字段
        List<String> tagsJsonList = blogService.getBaseMapper().selectObjs(queryWrapper)
                // 过滤掉空值
                .stream()
                .filter(ObjUtil::isNotNull)
                .map(Object::toString)
                .collect(Collectors.toList());
        // 统计每个标签出现的次数
        Map<String, Long> tagCountMap = tagsJsonList.stream()
                // 将JSON字符串转换为标签列表
                .flatMap(tagsJson -> JSONUtil.toList(tagsJson, String.class).stream())
                // 按标签分组并计数
                .collect(Collectors.groupingBy(tag -> tag, Collectors.counting()));
        // 将统计结果转换为响应对象列表，并按出现次数降序排序
        return tagCountMap.entrySet().stream()
                .sorted((e1, e2) -> Long.compare(e2.getValue(), e1.getValue()))
                .map(entry -> new BlogTagAnalyzeResponse(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());
    }

    /**
     * 获取博客分类分析数据
     *
     * @param blogCategoryAnalyzeRequest 博客分类分析请求参数
     * @param loginUser                  当前登录用户
     * @return 博客分类分析响应列表，包含分类名称和对应的博客数量
     */
    @Override
    public List<BlogCategoryAnalyzeResponse> getBlogCategoryAnalyze(BlogCategoryAnalyzeRequest blogCategoryAnalyzeRequest, User loginUser) {
        // 检查请求参数是否为空，为空则抛出参数错误异常
        ThrowUtils.throwIf(blogCategoryAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);

        // 检查权限
        checkSpaceAnalyzeAuth(blogCategoryAnalyzeRequest, loginUser);

        // 构造查询条件
        QueryWrapper<Blog> queryWrapper = new QueryWrapper<>();

        fillAnalyzeQueryWrapper(blogCategoryAnalyzeRequest, queryWrapper);
        // 使用 MyBatis-Plus 分组查询
        queryWrapper.select("category AS category",
                        "COUNT(*) AS count")
                .groupBy("category");

        // 查询并转换结果
        return blogService.getBaseMapper().selectMaps(queryWrapper)
                .stream()
                .map(result -> {
                    String category = result.get("category") != null ? result.get("category").toString() : "未分类";
                    Long count = ((Number) result.get("count")).longValue();
                    return new BlogCategoryAnalyzeResponse(category, count);
                })
                .collect(Collectors.toList());
    }

    private static void fillAnalyzeQueryWrapper(BlogAnalyzeRequest blogAnalyzeRequest, QueryWrapper<Blog> queryWrapper) {
        if (blogAnalyzeRequest.isQueryAll()) {
            return;
        }
        Long userId = blogAnalyzeRequest.getUserId();
        if (userId != null) {
            queryWrapper.eq("userId", userId);
            return;
        }
        throw new BusinessException(ErrorCode.PARAMS_ERROR, "未指定查询范围");
    }


    private void checkSpaceAnalyzeAuth(BlogAnalyzeRequest blogAnalyzeRequest, User loginUser) {
        // 检查权限
        if (blogAnalyzeRequest.isQueryAll()) {
            // 全权限校验：仅管理员可访问
            ThrowUtils.throwIf(!userService.isAdmin(loginUser), ErrorCode.NO_AUTH_ERROR, "无权访问所有文章");
        } else {
            // 校验
            Long userId = blogAnalyzeRequest.getUserId();
            ThrowUtils.throwIf(userId == null || userId <= 0, ErrorCode.PARAMS_ERROR);
        }
    }

}
